#pragma once
#include <atlsecurity.h>
#include "security_identifier.h"

//-------------------------------------------------------------------------------
class user_token
{
public:
	static user_token get_from_session_id(UINT session_id); // requires SYSTEM account
	static user_token get_from_process(DWORD process_id, DWORD access = TOKEN_ALL_ACCESS);
	static user_token get_from_thread(DWORD thread_id, DWORD access /*= TOKEN_ALL_ACCESS*/);
	static user_token get_from_login(const std::wstring& username, const std::wstring& domain = L"", const std::wstring& password = L"", DWORD logon_type = LOGON32_LOGON_INTERACTIVE, DWORD logon_provider = LOGON32_PROVIDER_DEFAULT);

public:
	user_token(HANDLE htoken);
	virtual ~user_token(void){}

	property_get(HANDLE,					token);
	property_get_set(security_identifier,				owner);
	property_get(security_identifier,			logon);
	property_get_set(security_identifier,			primary_group);
	property_get(std::vector<security_identifier>,	groups);
	property_get(bool,			is_primary_token);
	property_get(bool,			is_impersonation_token);
	
	bool impersonate(void){ return _token.ImpersonateLoggedOnUser() == TRUE; }
	void revert(void){ _token.Revert(); }
	HANDLE detach(void);

	operator HANDLE ();
	operator ATL::CAccessToken& ();

protected:
	user_token(){}

protected:
	ATL::CAccessToken	_token;
};
//-------------------------------------------------------------------------------